#!/bin/sh -e

export DESTDIR="$1"

patch -p1 < fix-curl.patch

# Instruct the compiler to trim absolute paths in resulting binaries and instead
# change them to relative paths ($PWD/... ./...).
export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix=$PWD=."

# Set shared linking as the default.
sed 's/\(crt_static_default = \)true/\1false/' \
    compiler/rustc_target/src/spec/linux_musl_base.rs > _
mv -f _ compiler/rustc_target/src/spec/linux_musl_base.rs

sed 's/\("files":{\)[^}]*/\1/' vendor/curl-sys/.cargo-checksum.json > _
mv -f _ vendor/curl-sys/.cargo-checksum.json

cat > config.toml <<EOF
[llvm]
link-shared = true

[build]
build     = "x86_64-unknown-linux-musl"
host      = [ "x86_64-unknown-linux-musl" ]
target    = [ "x86_64-unknown-linux-musl" ]

docs           = false
compiler-docs  = false
extended       = true
submodules     = false
python         = "python3"
locked-deps    = true
vendor         = true
tools          = [ "cargo", "rustfmt" ]
sanitizers     = false
profiler       = false
full-bootstrap = false
EOF

# If possible, use system rust to bootstrap.
maj="${2%%.*}"
min="${2%.*}"
min="${min#*.}"

# Fall back to vendor binaries if rustc, et al are not present, or if one of
# them suffered ABI breakage.
rust_version=$(rustc --version 2>/dev/null) || rust_version=null
cargo --version 2>/dev/null || rust_version=null
rustfmt --version 2>/dev/null || rust_version=null
rust_version="${rust_version#rustc }"

case "$rust_version" in
    "$maj.$min".*|"$maj.$((min - 1))".*)
        cat >> config.toml <<EOF
cargo          = "/usr/bin/cargo"
rustc          = "/usr/bin/rustc"
rustfmt        = "/usr/bin/rustfmt"
EOF
    ;;

    *)
        # This mimics the download process of rust's 'x.py'
        # bootstrap library to allow for the removal of the internet
        # connection requirement per build.
        mkdir -p "${cache_dir:=build/cache/2023-08-24}"

        for tarball in *.tar.xz\?no-extract; do
            mv -f "$tarball" "$cache_dir/${tarball%%\?no-extract}"
        done
    ;;
esac

cat >> config.toml <<EOF

[install]
prefix = "/usr"

[target.x86_64-unknown-linux-musl]
llvm-config = "/usr/bin/llvm-config"
crt-static  = false
sanitizers  = false

[dist]
src-tarball = false

[rust]
backtrace         = false
channel           = "stable"
codegen-tests     = false
codegen-units-std = 1
codegen-units     = 0
debug             = false
debug-assertions  = false
debuginfo-level   = 0
incremental       = false
jemalloc          = false
rpath             = false
dist-src          = false
EOF

# Workaround to get Rust to build in llvm-only environments.
# libgcc_s.so is needed for Rust's bootstrap binaries, on llvm-only systems
# this library does not exist. This hack creates it as alias to libunwind.
libunwind_path=$("$CC" -print-file-name=libunwind.so)
case $libunwind_path in */*)
    printf 'llvm-libunwind = "system"\n' >> config.toml

    mkdir -p libgcc

    printf 'INPUT(-lunwind)\n' > \
        libgcc/libgcc_s.so

    ln -sf "$libunwind_path" \
        libgcc/libgcc_s.so.1

    export \
        LD_LIBRARY_PATH="$PWD/libgcc:$LD_LIBRARY_PATH" \
        LIBRARY_PATH="$PWD/libgcc:$LIBRARY_PATH"
esac

python x.py build -j "$(grep -scF 'core id' /proc/cpuinfo)"
python x.py install

rm -rf \
    "$1/usr/lib/rustlib/src/" \
    "$1/usr/share/doc" \
    "$1/usr/share/zsh" \
    "$1/usr/lib/rustlib/uninstall.sh"

